#!/usr/bin/python
#encoding=utf-8

import ConfigParser
import socket
from optparse import OptionParser

ENABLE_MAGIC = False

try:
    import nids #optional
    end_states = (nids.NIDS_CLOSE, nids.NIDS_TIMEOUT, nids.NIDS_RESET)
    ENABLE_NIDS = True
except ImportError:
    ENABLE_NIDS = False
    
    
    
class JSunpack:
    version = "0.1"
    defaultReferer = ''
    ips = []
    
    def __init__(self):
        pass

def main():
    global ENABLE_NIDS
    global ENABLE_MAGIC
    socket.setdefaulttimeout(10) #network capable only if -a (--active) parameter specified

    message = '\n\t./jsunpackn.py [fileName]\n\t./jsunpackn.py -i [interfaceName]\n\tjsunpack-network version %s' % (JSunpack.version)

    if not ENABLE_NIDS:
        message += '\n\t[warning] pynids is disabled, while you cannot process pcap files or a network interface, you can still process JavaScript/HTML files\n'

    if not ENABLE_MAGIC:
        message += '\n\t[warning] magic library is disabled\n'
    
    parser = OptionParser(message)
    
    parser.add_option('-t', '--timeout', dest='timeout',
        help='limit on number of seconds to evaluate JavaScript', #default=30,
        action='store')
    parser.add_option('-r', '--redoEvalLimit', dest='redoevaltime',
        help='maximium evaluation time to allow processing of alternative version strings', #default=1,
        action='store')
    parser.add_option('-m', '--maxRunTime', dest='maxruntime',
        help='maximum running time (seconds; cumulative total). If exceeded, raise an alert (default: no limit)', default=None,
        action='store')
    parser.add_option('-f', '--fast-evaluation', dest='fasteval',
        help='disables (multiversion HTML,shellcode XOR) to improve performance', #default false
        action='store_true')
    parser.add_option('-u', '--urlFetch', dest='urlfetch',
        help='actively fetch specified URL (for fully active fetch use with -a)', default='',
        action='store')
    parser.add_option('-d', '--destination-directory', dest='outdir',
        help='output directory for all suspicious/malicious content', default='',
        action='store')
    parser.add_option('-c', '--config', dest='configfile',
        help='configuration filepath (default options.config)', default='options.config',
        action='store')
    parser.add_option('-s', '--save-all', dest='saveallfiles',
        help='save ALL original streams/files in output dir', #default=False,
        action='store_true')
    parser.add_option('-e', '--save-exes', dest='saveallexes',
        help='save ALL executable files in output dir', #default=False,
        action='store_true')
    parser.add_option('-a', '--active', dest='active',
        help='actively fetch URLs (only for use with pcap/file/url as input)', #default=False,
        action='store_true')
    parser.add_option('-p', '--proxy', dest='proxy',
        help='use a random proxy from this list (comma separated)',
        action='store')
    parser.add_option('-P', '--currentproxy', dest='currentproxy',
        help='use this proxy and ignore proxy list from --proxy',
        action='store')
    parser.add_option('-q', '--quiet', dest='quiet',
        help='limited output to stdout', #default=False,
        action='store_true')
    parser.add_option('-v', '--verbose', dest='verbose',
        help='verbose mode displays status for all files and decoding stages, without this option reports only detection', #default=False,
        action='store_true')
    parser.add_option('-V', '--very-verbose', dest='veryverbose',
        help='shows all decoding errors (noisy)', #default=False,
        action='store_true')
    parser.add_option('-g', '--graph-urlfile', dest='graphfile',
        help='filename for URL relationship graph, 60 URLs maximium due to library limitations',
        action='store')
    parser.add_option('-i', '--interface', dest='interface',
        help='live capture mode, use at your own risk (example eth0)', default='',
        action='store')
    parser.add_option('-D', '--debug', dest='debug',
        help='(experimental) debugging option, do not delete temporary files', default=False,
        action='store_true')
    parser.add_option('-J', '--javascript-decode-disable', dest='nojs',
        help='(experimental) dont decode anything, if you want to just use the original contents', default=False,
        action='store_true')

    (options, args) = parser.parse_args()

    #Start config file options
    fileopt = {}

    try:
        config = ConfigParser.RawConfigParser()
        if config.read(options.configfile):
            for path, value in config.items('paths'):
                if value == 'NULL':
                    value = ''
                fileopt[path] = value

            for path, value in config.items('decoding'):
                if value == 'True': value = True
                elif value == 'False': value = False
                fileopt[path] = value
        else:
            print 'Warning: options.config file not found'
    except ConfigParser.NoSectionError, e:
        print 'Fatal Error: invalid options.config file: %s' % (str(e))
        exit()
    
    for path in fileopt:
        if hasattr(options, path):
            if getattr(options, path):
                pass #cmdline has priority
            else:
                setattr(options, path, fileopt[path])
        else:
            setattr(options, path, fileopt[path])
            
    #these options must be int values
    options.timeout = int(options.timeout)
    options.redoevaltime = int(options.redoevaltime)
    options.maxruntime = int(options.maxruntime) 

    #end config file

    fin = open('rules', 'r')
    if fin:
        options.rules = fin.read()
        fin.close()

    fin = open('rules.ascii', 'r')
    if fin:
        options.rulesAscii = fin.read()
        fin.close()
    
    if options.htmlparse:
        fin = open(options.htmlparse, 'r')
        if fin:
            options.htmlparseconfig = fin.read()
            fin.close()   
    
    prevRooturl = {}
    if options.interface:
        js = JSunpack('interface', ['', '', ''], options)
        
if __name__ == "__main__":
    main() 
    
    
    